package com.syswin.lhztest.util;

import com.syswin.policy.Mail;
import org.apache.commons.lang3.StringUtils;

import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.regex.Pattern;

/**
 * @author:lhz
 * @date:2019/1/28 17:14
 */
public class MailUtil {

	private List<String> headers = new ArrayList(40);
	private List<String> attaches = new ArrayList();

	private Mail mail = null;

	private static class SingletonHolder {
		private static final MailUtil INSTANCE = new MailUtil();
	}

	public static final MailUtil getInstance() {
		return SingletonHolder.INSTANCE;
	}

	public MailUtil() {
		this.headers.add("Return-Path");
		this.headers.add("Received");
		this.headers.add("Resent-Date");
		this.headers.add("Resent-From");
		this.headers.add("Resent-Sender");
		this.headers.add("Resent-To");
		this.headers.add("Resent-Cc");
		this.headers.add("Resent-Bcc");
		this.headers.add("Resent-Message-Id");
		this.headers.add("Date");
		this.headers.add("From");
		this.headers.add("Sender");
		this.headers.add("Reply-To");
		this.headers.add("To");
		this.headers.add("Cc");
		this.headers.add("Bcc");
		this.headers.add("Message-Id");
		this.headers.add("X-MAIL");
		this.headers.add("References");
		this.headers.add("Comments");
		this.headers.add("Keywords");
		this.headers.add("X-Received");
		this.headers.add("X-Google-Smtp-Source");
		this.headers.add("DKIM-Signature");
		this.headers.add("X-Google-DKIM-Signature");
		this.headers.add("X-Gm-Message-State");
	}


	public Mail parserEmlFile(String emlPath) {
		Properties props = new Properties();
		Session session = Session.getDefaultInstance(props, null);
		InputStream inMsg;
		try {
			inMsg = new FileInputStream(emlPath);
			Message msg = new MimeMessage(session, inMsg);
			attaches.clear();
			mail = new Mail();
			parseHeaders(msg);
			parseContent(msg);
			mail.setAttachmentNames(attaches.toArray(new String[attaches.size()]));
		} catch (Exception e) {

		}
		return mail;
	}

	/**
	 * 防止邮件头
	 *
	 * @param msg
	 * @return
	 */
	private void parseHeaders(Message msg) {
		String s = "";
		for (String head : headers) {
			try {
				s = s + " " + ((MimeMessage) msg).getMatchingHeaderLines(new String[]{head}).nextElement();
			} catch (Exception e) {
			}
		}

		mail.setHeader(s);
	}

	private void parseContent(Message msg) throws Exception {
		//设置头
		mail.attachmentNames = new String[]{};
		// 发件人信息
		Address[] froms = msg.getFrom();
		if (froms != null) {
			// System.out.println("发件人信息:" + froms[0]);
			InternetAddress addr = (InternetAddress) froms[0];
			String senderStr =((MimeMessage) msg).getHeader("Sender", ";");
			mail.setFrom(StringUtils.isEmpty(senderStr)? addr.getAddress():senderStr);
			mail.setTo(((MimeMessage) msg).getHeader("to", ";"));
		}
		mail.setSubject(msg.getSubject());
		// getContent() 是获取包裹内容, Part相当于外包装
		Object o = msg.getContent();
		if (o instanceof Multipart) {
			Multipart multipart = (Multipart) o;
			reMultipart(multipart);
		} else if (o instanceof Part) {
			Part part = (Part) o;
			rePart(part);
		} else {
			System.out.println("parseEml类型" + msg.getContentType());
			System.out.println("parseEml内容" + msg.getContent());
			mail.setContent(removeHtmlTag(msg.getContent().toString()));
		}
	}

	/**
	 * @param part 解析内容
	 * @throws Exception
	 */
	private void rePart(Part part) throws Exception {

		if (part.getDisposition() != null) {
			String strFileNmae = part.getFileName();
			if (!StringUtils.isEmpty(strFileNmae)) {  // MimeUtility.decodeText解决附件名乱码问题
				strFileNmae = MimeUtility.decodeText(strFileNmae);
				attaches.add(strFileNmae);
				mail.setAttachmentSize(mail.getAttachmentSize() + 1);
//				InputStream in = part.getInputStream();// 打开附件的输入流
//				// 读取附件字节并存储到文件中
//				java.io.FileOutputStream out = new FileOutputStream(strFileNmae);
//				int data;
//				while ((data = in.read()) != -1) {
//					out.write(data);
//				}
//				in.close();
//				out.close();

			}
		} else {
			String str = "";
//			System.err.println(part.getContentType());
//			System.err.println(part.getContent());
//			System.err.println(part.getDisposition());
//			System.err.println(part.getDescription());
			if (part.getContentType().startsWith("text/plain")) {
				str = part.getContent().toString() + "";

			} else if (part.getContentType().startsWith("image/")) {
				str = removeHtmlTag(part.getContent().toString()) + "";
			} else {
				str = removeHtmlTag(part.getContent().toString()) + "";
			}

			mail.setContent(StringUtils.isEmpty(mail.getContent()) ? str : str + mail.getContent());
		}
	}

	/**
	 * @param multipart // 接卸包裹（含所有邮件内容(包裹+正文+附件)）
	 * @throws Exception
	 */
	private void reMultipart(Multipart multipart) throws Exception {
		// 依次处理各个部分
		for (int j = 0, n = multipart.getCount(); j < n; j++) {
			// System.out.println("处理第" + j + "部分");
			Part part = multipart.getBodyPart(j);// 解包, 取出 MultiPart的各个部分,
			// 每部分可能是邮件内容,
			// 也可能是另一个小包裹(MultipPart)
			// 判断此包裹内容是不是一个小包裹, 一般这一部分是 正文 Content-Type: multipart/alternative
			if (part.getContent() instanceof Multipart) {
				Multipart p = (Multipart) part.getContent();// 转成小包裹
				// 递归迭代
				reMultipart(p);
			} else {
				rePart(part);
			}
		}
	}

	/**
	 * 删除Html标签
	 *
	 * @param inputString
	 * @return
	 */
	private String removeHtmlTag(String inputString) {
		if (StringUtils.isEmpty(inputString))
			return inputString;
		String htmlStr = inputString; // 含html标签的字符串
		String textStr = "";
		Pattern p_script;
		java.util.regex.Matcher m_script;
		Pattern p_style;
		java.util.regex.Matcher m_style;
		Pattern p_html;
		java.util.regex.Matcher m_html;
		Pattern p_special;
		java.util.regex.Matcher m_special;
		try {
//定义script的正则表达式{或<script[^>]*?>[\\s\\S]*?<\\/script>
			String regEx_script = "<[\\s]*?script[^>]*?>[\\s\\S]*?<[\\s]*?\\/[\\s]*?script[\\s]*?>";
//定义style的正则表达式{或<style[^>]*?>[\\s\\S]*?<\\/style>
			String regEx_style = "<[\\s]*?style[^>]*?>[\\s\\S]*?<[\\s]*?\\/[\\s]*?style[\\s]*?>";
// 定义HTML标签的正则表达式
			String regEx_html = "<[^>]+>";
// 定义一些特殊字符的正则表达式 如：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
			String regEx_special = "\\&[a-zA-Z]{1,10};";

			p_script = Pattern.compile(regEx_script, Pattern.CASE_INSENSITIVE);
			m_script = p_script.matcher(htmlStr);
			htmlStr = m_script.replaceAll(""); // 过滤script标签
			p_style = Pattern.compile(regEx_style, Pattern.CASE_INSENSITIVE);
			m_style = p_style.matcher(htmlStr);
			htmlStr = m_style.replaceAll(""); // 过滤style标签
			p_html = Pattern.compile(regEx_html, Pattern.CASE_INSENSITIVE);
			m_html = p_html.matcher(htmlStr);
			htmlStr = m_html.replaceAll(""); // 过滤html标签
			p_special = Pattern.compile(regEx_special, Pattern.CASE_INSENSITIVE);
			m_special = p_special.matcher(htmlStr);
			htmlStr = m_special.replaceAll(""); // 过滤特殊标签
			textStr = htmlStr;
		} catch (Exception e) {
			e.printStackTrace();
		}
		textStr = textStr.replaceAll("//s*|/t|/r|/n", "");
		return textStr.trim();// 返回文本字符串
	}


	public static void main(String[] args) {
		System.out.println(MailUtil.getInstance().parserEmlFile("D:\\mailcomp\\testdata/2019/01/20/221921001.eml"));
	}
}
